package com.devicemantra.coordinate.operations;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.devicemantra.coordinate.dataobjects.CStateFactory;
import com.devicemantra.coordinate.exceptions.dataobjects.CDatabaseException;
import com.devicemantra.coordinate.exceptions.jaxb.CJAXBException;
import com.devicemantra.coordinate.exceptions.operations.CException;
import com.devicemantra.coordinate.exceptions.operations.CReadPayloadException;
import com.devicemantra.coordinate.exceptions.operations.CStateAlreadyExistsException;
import com.devicemantra.coordinate.exceptions.operations.CStateDoesNotExistsException;
import com.devicemantra.coordinate.exceptions.operations.CWritePayloadException;
import com.devicemantra.coordinate.interfaces.http.CHttpReader;
import com.devicemantra.coordinate.interfaces.http.CHttpWriter;
import com.devicemantra.coordinate.jaxb.*;



public class CRequestResponder 
{
	private HttpServletRequest mHTTPServletReq = null;
	private HttpServletResponse mHTTPServletResp = null;
	private Request mRequest = null;
	private CResponseBuilder mResponseBuilder = null;
	private int mRespCode;
	private String mReason;
	private OperationType mOperationType;
	private boolean mIsError;
	
	public CRequestResponder(HttpServletRequest pHTTPServletReq, HttpServletResponse pHTTPServletResp)
	{
		mHTTPServletReq = pHTTPServletReq;
		mHTTPServletResp = pHTTPServletResp;
		mResponseBuilder = new CResponseBuilder();
		mIsError = false;
	}
	
	@SuppressWarnings("unused")
	public void processEvent(OperationType pOperationType) throws CException 
	{
		/* First read the incoming request */
		String lXmlInputStr = null;
		/* Read the Content of the HTTP request as a String representation */
		try {
			lXmlInputStr = CHttpReader.getAsString(mHTTPServletReq);
		} catch(CReadPayloadException lException) {
			/* TODO : Internal server error 500 */
			mResponseBuilder.setStatus(500, "Internal Server Error :Reading Payload");
			throw new CException(lException.getMessage());
		}
		
		try {
			mRequest = JAXBRequestFactory.parseRequest(lXmlInputStr);
		} catch (CJAXBException e1) {
			// TODO Auto-generated catch block
			/* TODO : Parse  error 400 - Bad Request ? */
			mResponseBuilder.setStatus(400, "Bad Request : Parsing Payload");
			throw new CException(e1.getMessage());
		}
		
		mOperationType = mRequest.getCOperationType();
		System.out.println("Operation tpye " + mOperationType);
		
		if(mOperationType != pOperationType) {
			/** 409 Conflict - Indicates that the request could not be processed because of conflict in the request 
			 *  Requested operation is something different from the url hit */
			mResponseBuilder.setStatus(409, "Conflict in request from url");
			throw new CException("ERROR: Mismatch RequestData not matching Operation" + ": Request was directed at  " + pOperationType + " Operation data showed " + mOperationType);
		}
	
		/* Let us handle the event now */
		handleEvent();
		
	}
	
	@SuppressWarnings("unused")
	public void processFormEvent() throws CException 
	{
		/* First read the incoming request */
		String lXmlInputStr = null;
		
		
		
	}
	
	public void handleEvent() throws CException
	{
		/* Optimistic setting of status code and response string */
		mResponseBuilder.setStatus(200, "Success Operation executed");
		try {
			_handleEvent(mOperationType);
		}catch(CException e){
			throw new CException(e.getMessage());
		}
		
		
	}
	
	public boolean isMethodAllowed(OperationType pAllowedOperation)
	{
		boolean lIsAllowed = true;
		if(pAllowedOperation != mOperationType)
			lIsAllowed = false;
		
		return lIsAllowed;
	}
	
	
	private void _handleEvent(OperationType lRequestOperType) throws CException
	{
		System.out.println("Inside handle event for " + lRequestOperType);
		switch(lRequestOperType)
		{
			case ADD_STATE:
								AddState();
								break;
			case DELETE_STATE:
								DeleteState();
								break;
			case ADD_DEPARTMENT:
								AddDepartment();
								break;
			case DELETE_DEPARTMENT:
								DeleteDepartement();
								break;
			default:
								System.out.println("PANIC : Unsupported Operation request !!");
								break;
		}
	}
	
	public String getResponse() throws CException
	{
		String lXMLRespStr = null;
		if(mResponseBuilder != null)
		{
			lXMLRespStr = mResponseBuilder.getAsXML();
		}
		System.out.println("[CREQUESTRESPONDER] Response : " + lXMLRespStr);
		return lXMLRespStr;
	}
	
	public void respond() throws CException
	{
		String lXMLRespStr = getResponse();
		try {
			CHttpWriter.writeAsString(mHTTPServletResp, lXMLRespStr);
		} catch (CWritePayloadException e) {
			System.out.println("[ERROR] Could not write back to stream");
			e.printStackTrace();
			throw new CException(e.getMessage());
		}
	}
	
	private void AddDepartment() {
		// TODO Auto-generated method stub
		
	}

	private void DeleteDepartement() {
		// TODO Auto-generated method stub
		
	}

	private void DeleteState() throws CException {
		State lState = mRequest.getCRequestData().getCState();
		if( lState != null )
		{
			String lDelteStateName = lState.getName();
			try {
				CStateFactory.deleteState(lDelteStateName); 
				}catch (CDatabaseException e) {
				mResponseBuilder.setStatus(500, "Internal Server Error : Database related ");
				throw new CException(e.getMessage());
			} catch (CStateDoesNotExistsException e) {
				mResponseBuilder.setStatus(404, "State does not Exist");
				throw new CException(e.getMessage());
			}
		}
	}

	private void AddState() throws CException  {
		State lState = mRequest.getCRequestData().getCState();
		if( lState != null )
		{
			String lNewStateName = lState.getName();
			try {
				CStateFactory.createNewState(lNewStateName);
			} catch (CDatabaseException e) {
				mResponseBuilder.setStatus(500, "Internal Server Error : Could not persist to database");
				throw new CException(e.getMessage());
			} catch (CStateAlreadyExistsException e) {
				mResponseBuilder.setStatus(420, "State Already Exists");
				throw new CException(e.getMessage());
			}
		}
		
		
	}

	
}
